package ar.edu.itba.it.cg.grupo01.game;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import ar.edu.itba.it.cg.grupo01.game.terrain.Checkpoint;
import ar.edu.itba.it.cg.grupo01.game.terrain.DaytonaCP;
import ar.edu.itba.it.cg.grupo01.game.terrain.Flag;
import ar.edu.itba.it.cg.grupo01.utils.Utils;

import com.jme.bounding.BoundingBox;
import com.jme.math.Vector3f;

public enum GameMode {

	LAPS {

		@Override
		public URL getGameProperties(String circuitName) {
			return Utils.getResourceURL("properties/" + circuitName
					+ ".laps.properties");
		}

		@Override
		public String getScore(String scorePath, String circuitName) {
			return scorePath + circuitName + ".laps.score";
		}

		@Override
		public List<? extends Checkpoint> createCheckpoints(
				Properties properties) {
			int amount = Integer.valueOf(properties
					.getProperty("checkpoint.amount"));

			List<Checkpoint> checkpoints = new ArrayList<Checkpoint>(amount);

			for (int i = 1; i <= amount; i++) {
				DaytonaCP cp = createDaytonaCP(properties, i);
				cp.setModelBound(new BoundingBox());
				cp.updateModelBound();

				checkpoints.add(cp);
			}

			return checkpoints;

		}

		private DaytonaCP createDaytonaCP(Properties properties, int i) {
			String image = "flag.checkpoint";
			if (i == 1) {
				image = "flag.checkered";
			}

			float move = Float.valueOf(properties.getProperty("checkpoint"
					+ i + ".move"));

			Vector3f pos = Utils.getPosition(properties
					.getProperty("checkpoint" + i + ".pos"));
			DaytonaCP cp = new DaytonaCP("daytonaCP" + i, pos, move, Utils
					.getResourceURL(properties.getProperty(image)));

			return cp;
		}

		private long computeScore(long gameDuration, long maxScore,
				long zeroTime) {

			if (gameDuration > zeroTime) {
				return 0L;
			}

			return (long) (maxScore - (((double) maxScore / zeroTime) * gameDuration));
		}

		@Override
		public long getFinalScore(long gameDuration, long currentScore,
				long maxScore, long zeroTime) {
			return getTimeScore(gameDuration, maxScore, zeroTime, currentScore);
		}

		@Override
		public long getTimeScore(long currentTime, long maxScore,
				long zeroTime, long currentScore) {
			return computeScore(currentTime, maxScore, zeroTime);
		}

		@Override
		public GameEndingState gameEnded(int lap, long currentTime,
				Properties gameProperties) {

			if (lap == (Integer.valueOf(gameProperties.getProperty("laps")) + 1))
				return GameEndingState.WIN;

			return GameEndingState.NOTOVER;
		}

		@Override
		public long getDisplayTime(long currentTime,
				Properties gameModeProperties) {
			return currentTime;
		}

	},
	TIME_ATTACK {

		@Override
		public URL getGameProperties(String circuitName) {
			return Utils.getResourceURL("properties/" + circuitName
					+ ".timeattack.properties");
		}

		@Override
		public String getScore(String scorePath, String circuitName) {
			return scorePath + circuitName + ".timeattack.score";
		}

		@Override
		public List<? extends Checkpoint> createCheckpoints(
				Properties properties) {
			int amount = Integer.valueOf(properties
					.getProperty("checkpoint.amount"));
			int scaleFactor = Integer.valueOf(properties
					.getProperty("checkpoint.flagScale"));
			List<Checkpoint> checkpoints = new ArrayList<Checkpoint>(amount);

			long score = Long.valueOf(properties
					.getProperty("checkpoint.score"));

			for (int i = 1; i <= amount; i++) {
				Flag flag = createFlag(properties, i, scaleFactor, score);
				flag.setModelBound(new BoundingBox());
				flag.updateModelBound();

				checkpoints.add(flag);
			}

			return checkpoints;

		}

		private Flag createFlag(Properties properties, int i, int scaleFactor,
				long score) {
			String image = "flag.checkpoint";
			if (i == 1) {
				image = "flag.checkered";
			}

			Vector3f pos = Utils.getPosition(properties
					.getProperty("checkpoint" + i + ".pos"));
			Flag aFlag = new Flag("flag" + i, Utils.getResourceURL(properties
					.getProperty(image)), pos, score);

			aFlag.setLocalScale(scaleFactor);

			return aFlag;
		}

		@Override
		public long getFinalScore(long gameDuration, long currentScore,
				long maxScore, long zeroTime) {
			return currentScore;
		}

		@Override
		public long getTimeScore(long currentTime, long maxScore,
				long zeroTime, long currentScore) {
			return currentScore;
		}

		@Override
		public GameEndingState gameEnded(int lap, long currentTime,
				Properties gameProperties) {
			
			System.out.println("time " +  currentTime + "valueof" +  Long.valueOf(gameProperties.getProperty("timeLimit")));
			if (currentTime >= Long.valueOf(gameProperties
					.getProperty("timeLimit")))
				return GameEndingState.YOULOSE;

			if (lap == 2)
				return GameEndingState.WIN;

			return GameEndingState.NOTOVER;
		}

		@Override
		public long getDisplayTime(long currentTime,
				Properties gameModeProperties) {
			long value = Long.valueOf(gameModeProperties
					.getProperty("timeLimit"))
					- currentTime;

			return value < 0L ? 0L : value;
		}
	};

	public abstract URL getGameProperties(String circuitName);

	public abstract String getScore(String scorePath, String circuitName);

	public abstract List<? extends Checkpoint> createCheckpoints(
			Properties properties);

	public abstract long getFinalScore(long gameDuration, long currentScore,
			long maxScore, long zeroTime);

	public abstract long getTimeScore(long currentTime, long maxScore,
			long zeroTime, long currentScore);

	public abstract GameEndingState gameEnded(int lap, long currentTime,
			Properties gameProperties);

	public abstract long getDisplayTime(long currentTime,
			Properties gameModeProperties);
}
